package com.alibaba.citrus.cr.mn.order.center.facade.function.common;

import com.alibaba.citrus.cr.common.enums.GeneralStatusEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.mn.order.center.common.SetOrderTag;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BizInventoryQueryAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CargoZoneAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.InventoryAvailableQtyQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.LogisticWarehouseQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.InventoryAvailableQtyQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.LogisticWarehouseQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.function.check.CommonCheck;
import com.alibaba.citrus.cr.mn.order.center.facade.function.convert.BeanConverter;
import com.alibaba.citrus.cr.mn.order.center.facade.function.dataobject.AtomOrderDO;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.AtomOrderQueryRepository;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crb2btradecenter.domain.order.dto.QueryByOrderBizIdsRequest;
import com.epoch.app.crb2btradecenter.domain.order.dto.QueryByOrderNosV2Request;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crpricecenter.api.creditquery.dto.BatchQueryCreditListRequest;
import com.epoch.app.crpricecenter.api.creditquery.service.CreditQueryService;
import com.epoch.app.crpricecenter.model.dto.CreditInfoSDO;
import com.epoch.app.crpricecenter.model.dto.CreditQueryRequest;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomBatchSubmitRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomSubmitRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderBizBatchSubmitRequest;
import com.epoch.app.mnordercenter.sdo.SapCreditSDO;
import com.epoch.app.mnordercenter.service.MnOrderCenterService;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName SalesOrderBizCreateServiceImpl
 * @description: TODO
 * @date 2023/05/16 14:04
 * @version: 1.0
 */
public abstract class AbstractOrderBizSubmitService implements OrderBizSubmitService<OrderBizBatchSubmitRequest, OrderAtomBatchSubmitRequest, OrderAtomSubmitResponse> {
    private static final Log log = Log.getLogger(AbstractOrderBizSubmitService.class);
    private static final String NEGATIVE = "-";

    @Resource
    private CommonCheck commonCheck;

    @Resource
    private AtomOrderQueryRepository atomOrderQueryRepository;

    @Resource
    private BizInventoryQueryAdapter bizInventoryQueryAdapter;

    @Resource
    private CargoZoneAdapter cargoZoneAdapter;

    @Resource
    private CreditQueryService creditQueryService;

    @Resource
    private MnOrderCenterService mnOrderCenterService;
    @Resource
    private OrderService orderService;

    public abstract String getOrderTag();

    @Override
    public void preHandleRequestParams(OrderBizBatchSubmitRequest request) {
        StopWatchUtils.start("订单中心商业提交", "preHandleRequestParams");
        request.setOrderList(Optional.ofNullable(request.getOrderList()).orElse(Lists.newArrayList()));
        for (OrderAtomSubmitRequest salesOrder : request.getOrderList()) {
            if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                salesOrder.setBusinessUnitCode(request.getBusinessUnitCode());
            }
            if (StringUtils.isNotBlank(request.getBusinessType())) {
                salesOrder.setBusinessType(request.getBusinessType());
            }
            if (StringUtils.isNotBlank(request.getFromSys())) {
                salesOrder.setFromSys(request.getFromSys());
            }
            if (StringUtils.isNotBlank(request.getModifierCode())) {
                salesOrder.setModifierCode(request.getModifierCode());
            }
            if (StringUtils.isNotBlank(request.getOrderCategoryCode())) {
                salesOrder.setOrderCategoryCode(request.getOrderCategoryCode());
            }
        }
        StopWatchUtils.stop();
    }

    @Override
    public List<OrderAtomSubmitResponse> assembleBizBaseInfo(OrderBizBatchSubmitRequest request) {
        StopWatchUtils.start("订单中心商业提交", "initializeModifier");
        List<OrderAtomSubmitResponse> orderAtomSubmitResponses = initializeModifier(request);
        StopWatchUtils.stop();
        // 获取指定的单据信息
        StopWatchUtils.start("订单中心商业提交", "queryOrderByOrderBizIds");
        List<AtomOrderDO> atomOrders = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(request.getOrderList())){
            atomOrders = queryOrderByOrderBizIds(request, orderAtomSubmitResponses);
        }
        StopWatchUtils.stop();
        boolean needCheckStock = request.getOrderList().stream().anyMatch(it -> !Boolean.FALSE.equals(it.getCheckStock()));
        boolean needCheckCredit = request.getOrderList().stream().anyMatch(it -> !Boolean.FALSE.equals(it.getCheckCredit()));
        boolean needCheckCreditB = request.getOrderList().stream().anyMatch(it -> !Boolean.FALSE.equals(it.getCheckCreditB()));

        if (!needCheckStock && !needCheckCredit && !needCheckCreditB) {
            // 都不需要校验时，直接返回response，减少性能消耗
            return orderAtomSubmitResponses;
        }
        if (needCheckStock) {
            // 库存校验
            StopWatchUtils.start("订单中心商业提交", "checkInventoryAvailableQty");
            checkInventoryAvailableQty(request, atomOrders, orderAtomSubmitResponses);
            StopWatchUtils.stop();
        }

        if (needCheckCreditB && OrderCategoryEnum.STOCK.getCode().equals(request.getOrderCategoryCode())) {
            // 如果是一盘货默认信贷B校验
            StopWatchUtils.start("订单中心商业提交", "checkCreditB");
            checkCreditB(request, atomOrders, orderAtomSubmitResponses);
            StopWatchUtils.stop();
        }

        if (needCheckCredit) {
            // 信贷校验
            StopWatchUtils.start("订单中心商业提交", "checkCredit");
            checkCredit(request, atomOrders, orderAtomSubmitResponses);
            StopWatchUtils.stop();
        }

        return orderAtomSubmitResponses;
    }

    private List<AtomOrderDO> queryOrderByOrderBizIds(OrderBizBatchSubmitRequest request, List<OrderAtomSubmitResponse> responses) {
        List<String> bizOrderIds = request.getOrderList().stream().map(OrderAtomSubmitRequest::getSalesOrderNo).collect(Collectors.toList());
        QueryByOrderNosV2Request queryByOrderBizIdsRequest = new QueryByOrderNosV2Request();
        queryByOrderBizIdsRequest.setSalesOrderNo(bizOrderIds);
        queryByOrderBizIdsRequest.setFromSys(request.getOrderList().get(0).getFromSys());
        queryByOrderBizIdsRequest.setBusinessType(Integer.valueOf(request.getOrderList().get(0).getBusinessType()));
        queryByOrderBizIdsRequest.setBusinessUnitOutCode(request.getOrderList().get(0).getBusinessUnitCode());
        List<AtomOrderDO> atomOrderDOS = atomOrderQueryRepository.queryByOrderBizIds(queryByOrderBizIdsRequest, true);

        // 筛选指定类型的订单(销售、退货、换货)
        atomOrderDOS = atomOrderDOS.stream().filter(p -> p.getOrder().getOrderTag().equals(getOrderTag()))
                .collect(Collectors.toList());

        // 取出订单行为空的数据
        List<String> emptyOrderLineList = atomOrderDOS.stream().filter(p -> CollectionUtils.isEmpty(p.getOrderLines()))
                .map(AtomOrderDO::getSalesOrderNo).collect(Collectors.toList());

        bizOrderIds = atomOrderDOS.stream().map(AtomOrderDO::getSalesOrderNo).collect(Collectors.toList());
        log.info("AbstractOrderBizSubmitService#queryOrderByOrderBizIds#bizOrderIds={}",JSON.toJSONString(bizOrderIds));
        Iterator<OrderAtomSubmitRequest> iterator = request.getOrderList().iterator();
        while (iterator.hasNext()) {
            String salesOrderNo = iterator.next().getSalesOrderNo();
            if (!bizOrderIds.contains(salesOrderNo)) {
                // 订单不存在时，移除当前的订单请求
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(salesOrderNo);
                response.setErrorCode("OC-01-001-01-16-016");
                response.setMessage("订单不存在");
                responses.add(response);
                iterator.remove();
                continue;
            }

            if (emptyOrderLineList.contains(salesOrderNo)) {
                // 订单行不存在时，移除当前的订单请求
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(salesOrderNo);
                response.setErrorCode("OC-01-001-01-16-017");
                response.setMessage("订单行不存在");
                responses.add(response);
                iterator.remove();
                continue;
            }
        }

        return atomOrderDOS;
    }

    /**
     * 库存校验
     */
    private void checkInventoryAvailableQty(OrderBizBatchSubmitRequest request, List<AtomOrderDO> atomOrders, List<OrderAtomSubmitResponse> responses) {
        if (!SetOrderTag.NORMAL.equals(getOrderTag()) && !SetOrderTag.EXCHANGE.equals(getOrderTag())) {
            // 非销售订单或换货订单无需校验库存
            return;
        }

        if (CollectionUtils.isEmpty(request.getOrderList()) || CollectionUtils.isEmpty(atomOrders)) {
            return;
        }

        Map<String, AtomOrderDO> dbAtomOrderMap = atomOrders.stream()
                .collect(Collectors.toMap(AtomOrderDO::getSalesOrderNo, p -> p, (v1, v2) -> v1));

        // 取出需要校验库存的订单
        List<OrderAtomSubmitRequest> needCheckStockRequest = request.getOrderList().stream()
                .filter(orderAtomSubmitRequest -> !Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckStock()))
                .collect(Collectors.toList());
        List<AtomOrderDO> needCheckStockList = new ArrayList<>();
        for(OrderAtomSubmitRequest orderAtomSubmitRequest : needCheckStockRequest) {
            if (dbAtomOrderMap.containsKey(orderAtomSubmitRequest.getSalesOrderNo())) {
                needCheckStockList.add(dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo()));
            }
        }
        if (CollectionUtils.isEmpty(needCheckStockList)) {
            return;
        }

        // Key：库存工厂Code+库存地点Code or 逻辑仓库Code
        Map<String, LogisticWarehouseQueryDTO> logisticWarehouseQueryMap = queryLogisticWarehouseInfoList(needCheckStockList);
        // 库存可用数量
        Map<String, InventoryAvailableQtyQueryDTO> inventoryAvailableQtyQueryMap = queryInventoryAvailableQty(needCheckStockList, logisticWarehouseQueryMap);

        Iterator<OrderAtomSubmitRequest> iterator = needCheckStockRequest.iterator();
        while (iterator.hasNext()) {
            OrderAtomSubmitRequest orderAtomSubmitRequest = iterator.next();
            // 无需校验库存 SKIP
            if (Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckStock())) {
                continue;
            }
            // 校验库存
            AtomOrderDO atomOrderDO = dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo());

            // Key：库存工厂Code+库存地点Code or 逻辑仓库Code TODO 当前明细行 仓库唯一
            String warehouseKey = atomOrderDO.getOrderLines().get(0).getShippingWarehouseOutCode();
            LogisticWarehouseQueryDTO logisticWarehouseQueryResponse = logisticWarehouseQueryMap.get(warehouseKey);
            if (Objects.isNull(logisticWarehouseQueryResponse)) {
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(orderAtomSubmitRequest.getSalesOrderNo());
                response.setErrorCode("OC-01-001-01-16-045");
                response.setMessage("仓库地点不存在");
                responses.add(response);
                iterator.remove();
                continue;
            }
            if (!GeneralStatusEnum.YES.getCode().equals(logisticWarehouseQueryResponse.getStatus())) {
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(orderAtomSubmitRequest.getSalesOrderNo());
                response.setErrorCode("OC-01-001-01-16-045");
                response.setMessage("仓库地点不存在");
                responses.add(response);
                iterator.remove();
                continue;
            }
            // 按照逻辑仓_货品ID分组之后，对销售数量求和
            Map<String, Integer> warehouseIdOfQty = atomOrderDO.getOrderLines()
                    .stream()
                    .filter(p -> StringUtils.isNotBlank(p.getShippingWarehouseOutCode()))
                    .collect(Collectors.groupingBy(p -> String.format("%s_%s", p.getShippingWarehouseOutCode(), p.getScItemId()),
                            Collectors.reducing(0, OrderLine::getQuantity, Integer::sum)));

            for (Map.Entry<String, Integer> entry : warehouseIdOfQty.entrySet()) {
                String inventoryAvailableQtyKey = entry.getKey();
                Integer totalQuantity = entry.getValue();
                // 库存可用数量
                InventoryAvailableQtyQueryDTO inventoryAvailableQty = inventoryAvailableQtyQueryMap.get(inventoryAvailableQtyKey);

                // 当前行的库存可用量校验
                if (Objects.isNull(inventoryAvailableQty)
                        || Objects.isNull(inventoryAvailableQty.getAvailableQuantity())
                        || new BigDecimal(String.valueOf(totalQuantity)).compareTo(new BigDecimal(String.valueOf(inventoryAvailableQty.getAvailableQuantity()))) > 0) {
                    OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                    response.setSalesOrderNo(orderAtomSubmitRequest.getSalesOrderNo());
                    response.setErrorCode("OC-01-001-01-16-046");
                    response.setMessage("库存可用余量小于销售数量");
                    responses.add(response);
                    iterator.remove();
                    break;
                }
            }
        }
    }

    /**
     * 信贷校验
     */
    private void checkCredit(OrderBizBatchSubmitRequest request, List<AtomOrderDO> atomOrders, List<OrderAtomSubmitResponse> responses) {
        if (!SetOrderTag.NORMAL.equals(getOrderTag())) {
            // 非销售订单无需校验信贷
            return;
        }
        if (CollectionUtils.isEmpty(request.getOrderList()) || CollectionUtils.isEmpty(atomOrders)) {
            return;
        }

        Map<String, AtomOrderDO> dbAtomOrderMap = atomOrders.stream()
                .collect(Collectors.toMap(AtomOrderDO::getSalesOrderNo, p -> p, (v1, v2) -> v1));

        // 取出需要校验信贷的订单
        List<OrderAtomSubmitRequest> needCheckCreditRequest = request.getOrderList().stream()
                .filter(orderAtomSubmitRequest -> !Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckCredit()))
                .collect(Collectors.toList());
        List<AtomOrderDO> needCheckCreditList = new ArrayList<>();
        for(OrderAtomSubmitRequest orderAtomSubmitRequest : needCheckCreditRequest) {
            if (dbAtomOrderMap.containsKey(orderAtomSubmitRequest.getSalesOrderNo())) {
                needCheckCreditList.add(dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo()));
            }
        }
        if (CollectionUtils.isEmpty(needCheckCreditList)) {
            return;
        }

        // 信贷数据
        Map<String, Long> creditMap = Maps.newHashMap();
        if (OrderCategoryEnum.GROUP.getCode().equals(request.getOrderCategoryCode())) {
            creditMap.putAll(batchQueryGroupCreditList(needCheckCreditList));
        } else {
            creditMap.putAll(batchQueryCreditList(needCheckCreditList));
        }

        for (OrderAtomSubmitRequest orderAtomSubmitRequest : needCheckCreditRequest) {
            // 无需校验信贷 SKIP
            if (Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckCredit())) {
                continue;
            }
            AtomOrderDO atomOrderDO = dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo());

            // 校验信贷
            if (!isCreditMoneyEnough(atomOrderDO, creditMap)) {
                // 信贷校验余额不足不影响单据提交
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(orderAtomSubmitRequest.getSalesOrderNo());
                response.setErrorCode("OC-01-001-01-16-042");
                response.setMessage("SAP信贷额度查询额度不够");
                responses.add(response);
                throw new FunctionException("OC-01-001-01-16-042", "SAP信贷额度查询额度不够");
            }
        }
    }

    /**
     * 信贷B校验
     */
    private void checkCreditB(OrderBizBatchSubmitRequest request, List<AtomOrderDO> atomOrders, List<OrderAtomSubmitResponse> responses) {
        if (!SetOrderTag.NORMAL.equals(getOrderTag())) {
            // 非销售订单无需校验信贷
            return;
        }
        if (CollectionUtils.isEmpty(request.getOrderList()) || CollectionUtils.isEmpty(atomOrders)) {
            return;
        }
        //根据关联单号查询F-B订单
        List<String> relationNos = Lists.newArrayList();
        atomOrders.forEach(it -> relationNos.add(it.getOrder().getRelationNo()));
        if (CollectionUtils.isEmpty(relationNos)) {
            log.info("checkCreditB relationNos={}",JSON.toJSONString(relationNos));
            return;
        }
        QueryByOrderBizIdsRequest queryByOrderBizIdsRequest = new QueryByOrderBizIdsRequest();
        queryByOrderBizIdsRequest.setOrderBizIds(relationNos);
        //F-B订单
        Result<List<Order>> orders = orderService.queryByOrderBizIds(queryByOrderBizIdsRequest);
        log.info("AbstractOrderBizSubmitService#checkCreditB#orders={}",JSON.toJSONString(orders.getResult()));
        List<AtomOrderDO> list = Lists.newArrayList();
        orders.getResult().forEach(it -> {
            AtomOrderDO atomOrderDO = new AtomOrderDO();
            atomOrderDO.setOrder(it);
            list.add(atomOrderDO);
        });


        //key = F-B订单的relationNo 是B-b的biz_ord_id value = F-B订单
        Map<String, AtomOrderDO> dbAtomOrderMap = list.stream()
                .collect(Collectors.toMap(AtomOrderDO::getRelationNo, p -> p, (v1, v2) -> v1));

        // 取出需要校验信贷的F-B订单
        List<OrderAtomSubmitRequest> needCheckCreditRequest = request.getOrderList().stream()
                //默认校验B
                .filter(orderAtomSubmitRequest -> !Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckCreditB()))
                .collect(Collectors.toList());
        //F-B需要检查信贷的数据
        List<AtomOrderDO> needCheckCreditList = new ArrayList<>();
        for(OrderAtomSubmitRequest orderAtomSubmitRequest : needCheckCreditRequest) {
            //这个是B-b的请求，salesOrderNo是B-b的订单号，不是F-B的

            if (dbAtomOrderMap.containsKey(orderAtomSubmitRequest.getSalesOrderNo())) {
                needCheckCreditList.add(dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo()));
            }
        }
        log.info("AbstractOrderBizSubmitService#checkCreditB#needCheckCreditList={}",JSON.toJSONString(needCheckCreditList));
        if (CollectionUtils.isEmpty(needCheckCreditList)) {
            return;
        }

        // 信贷B数据
        Map<String, Long> creditMap = Maps.newHashMap();
        //查询信贷记录
        creditMap.putAll(batchQueryCreditList(needCheckCreditList));
        log.info("AbstractOrderBizSubmitService#checkCreditB#creditMap={}",JSON.toJSONString(creditMap));

        for (OrderAtomSubmitRequest orderAtomSubmitRequest : needCheckCreditRequest) {
            // 无需校验信贷 SKIP
            if (Boolean.FALSE.equals(orderAtomSubmitRequest.getCheckCreditB())) {
                continue;
            }
            //
            AtomOrderDO atomOrderDO = dbAtomOrderMap.get(orderAtomSubmitRequest.getSalesOrderNo());
            log.info("AbstractOrderBizSubmitService#checkCreditB#atomOrderDO={}",JSON.toJSONString(atomOrderDO));
            // 校验信贷
            if (!isCreditMoneyEnough(atomOrderDO, creditMap)) {
                // 信贷校验余额不足不影响单据提交
                OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
                response.setSalesOrderNo(orderAtomSubmitRequest.getSalesOrderNo());
                response.setErrorCode("OC-01-001-01-16-042");
                response.setMessage("SAP信贷额度查询额度不够");
                responses.add(response);
                throw new FunctionException("OC-01-001-01-16-042", "SAP信贷额度查询额度不够");
            }
        }
    }

    /**
     * 信贷余额是否充足
     */
    private boolean isCreditMoneyEnough(AtomOrderDO atomOrderDO, Map<String, Long> creditInfoMap) {
        Long mainOrderSum = Optional.ofNullable(atomOrderDO.getOrderLines()).orElse(Lists.newArrayList()).stream()
                .map(p -> {
                    if (!isNumber(p.getUnitPrice()) || Objects.isNull(p.getQuantity())) {
                        return 0L;
                    }

                    String unitPrice = StringUtils.isBlank(p.getActivityPrice()) ? p.getUnitPrice() : p.getActivityPrice();
                    return new BigDecimal(unitPrice).multiply(new BigDecimal(p.getQuantity())).longValue();
                }).reduce(0L, Long::sum);

        String creditKey = String.format("%s-%s-%s-%s", atomOrderDO.getOrder().getOrganizationOutCode(),
                atomOrderDO.getOrder().getCustomerCode(),
                atomOrderDO.getOrder().getChannelCode(), atomOrderDO.getOrder().getProductGroupCode());
        Long balance = creditInfoMap.get(creditKey);
        log.info("信贷校验 mainOrderSum={}, balance={},creditInfoMap={}", mainOrderSum, balance,JSON.toJSONString(creditInfoMap));
        if (Objects.nonNull(balance)) {

            if (balance < mainOrderSum) {
                return false;
            }
            balance = balance - mainOrderSum;
            creditInfoMap.put(creditKey, balance);
        }else{
            //如果没有配置信贷，拦截
            return false;
        }
        return true;
    }

    private boolean isNumber(String params) {
        if (StringUtils.isBlank(params)) {
            return false;
        }
        String reg = "^\\d+(\\.\\d{1,})$|(^[1-9]\\d*$)";
        if (!StringUtils.isNumeric(params) && !Pattern.compile(reg).matcher(params).matches()) {
            return false;
        }
        return true;
    }

    @Override
    public OrderAtomBatchSubmitRequest convertAtomRequest(OrderBizBatchSubmitRequest request) {
        return BeanConverter.convert(request, new OrderAtomBatchSubmitRequest());
    }

    @Override
    public void printExecConsumerTime() {
        StopWatchUtils.print("AbstractOrderBizSubmitService#batchsubmit");
    }

    private List<OrderAtomSubmitResponse> initializeModifier(OrderBizBatchSubmitRequest bizOrderCreateList) {
        List<String> modifierCodeList = bizOrderCreateList.getOrderList().stream()
                .map(OrderAtomSubmitRequest::getModifierCode)
                .collect(Collectors.toList());
        Map<String, Modifiers> modifiers = commonCheck.getModifiers(modifierCodeList);

        Iterator<OrderAtomSubmitRequest> iterator = bizOrderCreateList.getOrderList().iterator();
        List<OrderAtomSubmitResponse> respList = new ArrayList<>();
        while (iterator.hasNext()) {
            OrderAtomSubmitRequest orderAtomCloseRequest = iterator.next();

            OrderAtomSubmitResponse response = new OrderAtomSubmitResponse();
            response.setSalesOrderNo(orderAtomCloseRequest.getSalesOrderNo());

            if (StringUtils.isNotBlank(orderAtomCloseRequest.getModifierCode())) {
                Modifiers modifier = modifiers.get(orderAtomCloseRequest.getModifierCode());
                if (Objects.isNull(modifier) || modifier.getStatus() != 1) {
                    response.setMessage("人员不存在");
                    respList.add(response);
                    iterator.remove();
                    continue;
                }
                orderAtomCloseRequest.setModifierName(modifier.getName());
            }
        }
        return respList;
    }

    private Map<String, LogisticWarehouseQueryDTO> queryLogisticWarehouseInfoList(List<AtomOrderDO> atomOrders) {
        List<LogisticWarehouseQueryRequest> logisticWarehouseQueryRequests = Lists.newArrayList();
        Set<String> dupLogisticWarehouseCode = Sets.newHashSet();
        Set<String> dupAddressAndFactoryCode = Sets.newHashSet();
        for (AtomOrderDO atomOrder : atomOrders) {
            for (OrderLine orderDetail : atomOrder.getOrderLines()) {
                if (StringUtils.isNotBlank(orderDetail.getShippingWarehouseOutCode())) {
                    if (!dupLogisticWarehouseCode.contains(orderDetail.getShippingWarehouseOutCode())) {

                        LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
                        queryRequest.setLogicWarehouseCode(orderDetail.getShippingWarehouseOutCode());
                        logisticWarehouseQueryRequests.add(queryRequest);

                        dupLogisticWarehouseCode.add(orderDetail.getShippingWarehouseOutCode());
                    }
                } else if (StringUtils.isNotBlank(orderDetail.getDeliveryFactoryCode()) && StringUtils.isNotBlank(orderDetail.getStockCode())) {
                    if (!dupAddressAndFactoryCode.contains(String.format("%s_%s", orderDetail.getDeliveryFactoryCode(), orderDetail.getStockCode()))) {

                        LogisticWarehouseQueryRequest queryRequest = new LogisticWarehouseQueryRequest();
                        queryRequest.setFactoryCode(orderDetail.getDeliveryFactoryCode());
                        queryRequest.setStorageLocation(orderDetail.getStockCode());
                        logisticWarehouseQueryRequests.add(queryRequest);

                        dupAddressAndFactoryCode.add(String.format("%s_%s", orderDetail.getDeliveryFactoryCode(), orderDetail.getStockCode()));
                    }
                }
            }
        }

        if (CollectionUtils.isEmpty(logisticWarehouseQueryRequests)) {
            return Maps.newHashMap();
        }

        List<LogisticWarehouseQueryDTO> listResult = cargoZoneAdapter.queryCargoZoneListByParam(logisticWarehouseQueryRequests);
        if (CollectionUtils.isEmpty(listResult)) {
            return Maps.newHashMap();
        }

        Map<String, LogisticWarehouseQueryDTO> logisticWarehouseQueryResponseMap = Maps.newHashMap();
        for (LogisticWarehouseQueryDTO logisticWarehouseQueryResponse : listResult) {
            String factoryStockCode = String.format("%s_%s", logisticWarehouseQueryResponse.getSapFactoryCode(), logisticWarehouseQueryResponse.getWarehouseCode());
            logisticWarehouseQueryResponseMap.put(factoryStockCode, logisticWarehouseQueryResponse);
            logisticWarehouseQueryResponseMap.put(logisticWarehouseQueryResponse.getCode(), logisticWarehouseQueryResponse);
        }

        return logisticWarehouseQueryResponseMap;
    }

    private Map<String, InventoryAvailableQtyQueryDTO> queryInventoryAvailableQty(List<AtomOrderDO> atomOrders, Map<String, LogisticWarehouseQueryDTO> logisticWarehouseQueryMap) {
        List<InventoryAvailableQtyQueryRequest> inventoryAvailableQtyQueryRequests = Lists.newArrayList();
        for (AtomOrderDO atomOrderDO : atomOrders) {
            Map<String, List<OrderLine>> warehouseOfOrderLineList1 = atomOrderDO.getOrderLines()
                    .stream()
                    .filter(p -> StringUtils.isNotBlank(p.getShippingWarehouseOutCode()))
                    .collect(Collectors.groupingBy(OrderLine::getShippingWarehouseOutCode));

            warehouseOfOrderLineList1.forEach((warehouseCode, orderLineList) -> {
                List<String> productCodes = orderLineList.stream().map(OrderLine::getScItemOutCode).distinct().collect(Collectors.toList());

                InventoryAvailableQtyQueryRequest queryRequest = new InventoryAvailableQtyQueryRequest();
                queryRequest.setLogicWarehouseCode(warehouseCode);
                queryRequest.setGoodsCodeList(productCodes);

                inventoryAvailableQtyQueryRequests.add(queryRequest);
            });

            Map<String, List<OrderLine>> warehouseOfOrderLineList2 = atomOrderDO.getOrderLines()
                    .stream()
                    .filter(p -> StringUtils.isNotBlank(p.getDeliveryFactoryCode()) && StringUtils.isNotBlank(p.getStockCode()))
                    .collect(Collectors.groupingBy(p -> String.format("%s_%s", p.getDeliveryFactoryCode(), p.getStockCode())));

            warehouseOfOrderLineList2.forEach((deliveryFactoryStockCode, orderLineList) -> {

                LogisticWarehouseQueryDTO logisticWarehouseQueryDTO = logisticWarehouseQueryMap.get(deliveryFactoryStockCode);
                if (Objects.isNull(logisticWarehouseQueryDTO)) {
                    return;
                }
                List<String> productCodes = orderLineList.stream().map(OrderLine::getScItemOutCode).distinct().collect(Collectors.toList());

                InventoryAvailableQtyQueryRequest queryRequest = new InventoryAvailableQtyQueryRequest();
                queryRequest.setLogicWarehouseCode(logisticWarehouseQueryDTO.getCode());
                queryRequest.setGoodsCodeList(productCodes);

                inventoryAvailableQtyQueryRequests.add(queryRequest);
            });
        }
        if (CollectionUtils.isEmpty(inventoryAvailableQtyQueryRequests)) {
            return Maps.newHashMap();
        }

        List<InventoryAvailableQtyQueryDTO> inventoryAvailableQtyList =
                bizInventoryQueryAdapter.queryInventoryAvailableQty(inventoryAvailableQtyQueryRequests);

        if (CollectionUtils.isEmpty(inventoryAvailableQtyList)) {
            return Maps.newHashMap();
        }

        return inventoryAvailableQtyList.stream()
                .collect(Collectors.toMap(p -> p.getWarehouseCode() + "_" + p.getGoodsId(), p -> p, (v1, v2) -> v1));
    }

    private Map<String, Long> batchQueryCreditList(List<AtomOrderDO> atomOrderDOS) {
        List<CreditQueryRequest> creditQueryRequestList = atomOrderDOS.stream().map(p -> {
            CreditQueryRequest creditQueryRequest = new CreditQueryRequest();
            creditQueryRequest.setCustomerCode(p.getOrder().getCustomerCode());
            creditQueryRequest.setChannelCode(p.getOrder().getChannelCode());
            creditQueryRequest.setOrganizationCode(p.getOrder().getOrganizationOutCode());
            creditQueryRequest.setItemGroupCode(p.getProductGroupCode());
            return creditQueryRequest;
        }).collect(Collectors.toList());

        //去重同条件信贷查询
        List<CreditQueryRequest> distinctList = creditQueryRequestList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() ->
                                new TreeSet<>(Comparator.comparing(o -> o.getCustomerCode() + "-"
                                        + o.getChannelCode() + "-"
                                        + o.getOrganizationCode() + "-"
                                        + o.getItemGroupCode()))
                        ), ArrayList::new));
        BatchQueryCreditListRequest batchQueryCreditListRequest = new BatchQueryCreditListRequest();
        batchQueryCreditListRequest.setRequestList(distinctList);
        Result<List<CreditInfoSDO>> batchQueryCreditList =
                creditQueryService.batchQueryCreditList(batchQueryCreditListRequest);
        log.info("AbstractOrderBizSubmitService#batchQueryCreditList#batchQueryCreditList={}#batchQueryCreditListRequest={}",JSON.toJSONString(batchQueryCreditList),JSON.toJSONString(batchQueryCreditListRequest));
        Map<String, Long> creditMap = Maps.newHashMap();
        if (Objects.nonNull(batchQueryCreditList) && CollectionUtils.isNotEmpty(batchQueryCreditList.getResult())) {
            for (CreditInfoSDO creditInfoSDO : batchQueryCreditList.getResult()) {
                if (Objects.nonNull(creditInfoSDO.getBalance())) {
                    String creditKey = String.format("%s-%s-%s-%s",
                            creditInfoSDO.getOrganizationCode(),
                            creditInfoSDO.getCustomerCode(),
                            creditInfoSDO.getChannelCode(),
                            creditInfoSDO.getItemGroupCode());
                    long balance = new BigDecimal(creditInfoSDO.getBalance()).multiply(new BigDecimal(100)).longValue();
                    creditMap.put(creditKey, balance);
                }
            }
        }
        return creditMap;
    }

    private Map<String, Long> batchQueryGroupCreditList(List<AtomOrderDO> atomOrderDOS) {
        if (CollectionUtils.isEmpty(atomOrderDOS)) {
            return Maps.newHashMap();
        }

        //去重同条件信贷查询
        List<QueryCreditRequest> distinctList = atomOrderDOS.stream().map(o->{
            QueryCreditRequest creditRequest=new QueryCreditRequest();
            creditRequest.setSoldToPartyCode(o.getOrder().getCustomerCode());
            creditRequest.setSalesOrganizationCode(o.getOrder().getOrganizationOutCode());
            creditRequest.setBusinessType(String.valueOf(o.getOrder().getBusinessType()));
            creditRequest.setDistributionChannelCode(o.getOrder().getChannelCode());
            return creditRequest;
                }
        ).collect(
                Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(o ->
                                String.format("%s-%s-%s-%s",
                                        o.getSalesOrganizationCode(),
                                        o.getSoldToPartyCode(),
                                        o.getDistributionChannelCode(),
                                        o.getBusinessType())))), ArrayList::new));

        QueryGroupCreditRequest queryGroupCreditRequest = new QueryGroupCreditRequest();
        queryGroupCreditRequest.setData(distinctList);
        log.info("SalesOrderCreateBizAssembleOfCustomerCenter#batchQueryGroupCreditList request: {}", JSON.toJSONString(queryGroupCreditRequest));
        Result<QueryCreditResponse> result = mnOrderCenterService.queryGroupCredit(queryGroupCreditRequest);
        log.info("SalesOrderCreateBizAssembleOfCustomerCenter#batchQueryGroupCreditList result: {}", JSON.toJSONString(result));
        if (Objects.isNull(result) || Objects.isNull(result.getResult()) || CollectionUtils.isEmpty(result.getResult().getData())) {
            return Maps.newHashMap();
        }

        Map<String, Long> creditMap = Maps.newHashMap();
        for (SapCreditSDO sapCreditSDO : result.getResult().getData()) {
            if (Objects.isNull(sapCreditSDO.getDMBTR())) {
                continue;
            }
            try {
                String creditKey = String.format("%s-%s-%s-%s",
                        sapCreditSDO.getVKORG(), // 销售组织
                        sapCreditSDO.getKUNNR(), // 客户售达方
                        sapCreditSDO.getVTWEG(), // 分销渠道
                        sapCreditSDO.getSPART()); // 产品组
                String dmbtr = sapCreditSDO.getDMBTR().replaceAll(" ", "");
                if (dmbtr.contains(NEGATIVE)){
                    dmbtr=changeNegativePosition(dmbtr);
                }
                long balance = new BigDecimal(dmbtr)
                        .multiply(new BigDecimal(100)).longValue();
                creditMap.put(creditKey, balance);
            } catch (Exception e) {
                log.error("SalesOrderCreateBizAssembleOfCustomerCenter#batchQueryGroupCreditList error", e);
            }
        }
        return creditMap;
    }

    //负号倒转
    private String changeNegativePosition(String number){
        return NEGATIVE + number.replaceAll(NEGATIVE,"");
    }
}
